﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Windows.Forms;
using GRWL.BZSC.UI.BaseDataSvc;
using System.Data;
using System.Reflection;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using UserCtrl;

namespace GRWL.BZSC.UI
{

    public static class TheColor
    {
        public static Color GridViewDataInput = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(255)))), ((int)(((byte)(192)))));
        public static Color GridViewDataShow = Color.LightGoldenrodYellow;
    }


    #region 系统登陆用户信息
    /// <summary>
    /// 系统登陆用户信息
    /// </summary>
    public static class SysLoginUserInfo
    {
        /// <summary>
        /// 系统登陆用户编号
        /// </summary>
        public static int UserId { get; set; }
        /// <summary>
        /// 系统登陆用户名称
        /// </summary>
        public static string UserName { get; set; }

        public static string UserCode { get; set; }

        public static int? DepartmentId { get; set; }

        public static string DepartmentCode { get; set; }

        public static string DepartmentName { get; set; }

        /// <summary>
        /// 给综合平台外部登录绑定到系统
        /// </summary>
        /// <param name="userCode"></param>
        /// <returns></returns>
        public static bool Login(string userCode)
        {
            try
            {
                using (BaseDataClient bdc = new GRWL.BZSC.UI.BaseDataSvc.BaseDataClient())
                {
                    bdc.Open();
                    XUser user = bdc.GetLoginUser(userCode);
                    if (user != null)
                    {
                        SysLoginUserInfo.UserId = user.User.id;
                        SysLoginUserInfo.UserName = user.User.name;
                        SysLoginUserInfo.UserCode = user.User.code;
                        SysLoginUserInfo.DepartmentCode = user.DepartmentCode;
                        SysLoginUserInfo.DepartmentId = user.User.department;
                        SysLoginUserInfo.DepartmentName = user.DepartmentName;
                        return true;
                    }
                    bdc.Close();
                }
            }
            catch { }
            return false;
        }
    }
    #endregion

    #region 通用方法
    public static class Common
    {
        #region 枚举
        /// <summary>
        /// 窗体委托回调操作类型
        /// </summary>
        public enum OperateType
        {
            /// <summary>
            /// 新增操作
            /// </summary>
            Add = 1,
            /// <summary>
            /// 更新操作
            /// </summary>
            Update,
            /// <summary>
            /// 删除操作
            /// </summary>
            Delete
        }

        /// <summary>
        /// 单据窗体操作类型, BaseFrm 中 EditStatus 属性使用。
        /// </summary>
        public enum BillOperateType
        {
            /// <summary>
            /// 新增操作
            /// </summary>
            Add,
            /// <summary>
            /// 更新操作
            /// </summary>
            Update,
            /// <summary>
            /// 删除操作
            /// </summary>
            Delete,
            /// <summary>
            /// 查看操作
            /// </summary>
            View,
            /// <summary>
            /// 无操作
            /// </summary>
            None
        }

        #endregion

        public static void CellFormatColor(object sender, DataGridViewCellFormattingEventArgs e, Common.BillOperateType EditStatus)
        {
            UDataGridView TheView = (UDataGridView)sender;
            if ((EditStatus == Common.BillOperateType.Add) || (EditStatus == Common.BillOperateType.Update))
            {
                if (!TheView.Columns[e.ColumnIndex].ReadOnly)
                {
                    e.CellStyle.BackColor = TheColor.GridViewDataInput;
                }
            }
            else
            {
                if ((e.RowIndex % 2) == 1)
                    e.CellStyle.BackColor = TheColor.GridViewDataShow;
            }
        }

        #region 其它方法

        /// <summary>
        /// 加载选项数据并绑定选中项
        /// </summary>
        /// <param name="cb">窗体ComboBox</param>
        /// <param name="optionType">option类型</param>
        /// <param name="selectedText">选中项</param>
        public static void BindOptionComboBox(ComboBox cb, GRWL.BZSC.Common.EnumCommon.OptionType optionType, BaseDataClient bdc, string selectedText)
        {
            try
            {
                TB_Options[] options = bdc.GetOptionTree(optionType.ToString());
                if (options != null)
                {
                    cb.Items.Clear();
                    foreach (TB_Options o in options)
                        cb.Items.Add(o.name);
                    if (!string.IsNullOrEmpty(selectedText))
                        cb.SelectedItem = selectedText;
                }
            }
            catch { }
        }

        /// <summary>
        /// 通用选项数据绑定treeview树
        /// </summary>
        /// <param name="tv">传入TreeView</param>
        /// <param name="options">通用选项数据</param>
        /// <param name="rootName">显示根节点名称</param>
        public static void BindOptionTree(UserCtrl.UTreeView tv, TB_Options[] options, string rootName)
        {
            if (tv.Nodes.Count > 0)
                tv.Nodes.Clear();
            TreeNode node = new TreeNode(rootName);
            node.ImageIndex = 1;
            initChild(node, options, 0);
            tv.Nodes.Add(node);
        }

        private static void initChild(TreeNode node, TB_Options[] options, int parentId)
        {
            var ops = from o in options where o.parentId == parentId select o;
            if (options != null)
            {
                foreach (TB_Options child in ops)
                {
                    TreeNode newNode = node.Nodes.Add(child.id.ToString(), child.code + "[" + child.name + "]");
                    newNode.Tag = child.code;
                    newNode.ImageIndex = 2;
                    initChild(newNode, options, child.id);
                }
            }
        }

        /// <summary>
        /// 工序数据绑定treeview
        /// </summary>
        /// <param name="tv"></param>
        /// <param name="options"></param>
        /// <param name="rootName"></param>
        public static void BindWorkstageTree(UserCtrl.UTreeView tv, WorkstageTreeNode[] wsNodes, string rootName)
        {
            if (tv.Nodes.Count > 0)
                tv.Nodes.Clear();
            TreeNode node = new TreeNode(rootName);
            initChild(node, wsNodes, 0);
            tv.Nodes.Add(node);
        }


        private static void initChild(TreeNode node, WorkstageTreeNode[] wsNodes, int parentId)
        {
            var ops = from o in wsNodes where o.ParentId == parentId select o;
            if (wsNodes != null)
            {
                foreach (WorkstageTreeNode child in ops)
                {
                    TreeNode newNode = node.Nodes.Add(child.Id.ToString(), child.Code + "[" + child.Name + "]");
                    newNode.Tag = child.Code;
                    initChild(newNode, wsNodes, child.Id);
                }
            }
        }
        /// <summary>
        /// 绑定部门资料
        /// </summary>
        /// <param name="tv"></param>
        /// <param name="departments"></param>
        /// <param name="rootName"></param>
        public static void BindDeptTree(UserCtrl.UTreeView tv, TB_Department[] departments, string rootName)
        {
            if (tv.Nodes.Count > 0)
                tv.Nodes.Clear();
            TreeNode node = new TreeNode(rootName);
            tv.Nodes.Add(node);
            if (departments != null)
                initChild(node, departments, 0);
        }

        private static void initChild(TreeNode node, TB_Department[] departments, int parentId)
        {
            var depts = from d in departments where d.parentId == parentId select d;

            if (depts != null)
            {
                foreach (TB_Department child in depts)
                {
                    TreeNode newNode = node.Nodes.Add(child.id.ToString(), child.name);
                    newNode.Tag = child.id;
                    initChild(newNode, departments, child.id);
                }
            }
        }

        public static void BindDeptComboBox(ComboBox cb, TB_Department[] departments)//绑定部门名到ComboBox上
        {
            if (cb == null || departments == null)
                return;
            cb.Items.Clear();
            var depts = from d in departments select d;
            if (depts != null)
            {
                foreach (TB_Department tb in depts)
                {
                    cb.Items.Add(tb.name + "[" + tb.id + "]");
                }
            }
        }


        public static decimal StringToDecimal(string InputString)
        {
            decimal ReturnValue = 0;
            try
            {
                if (!String.IsNullOrEmpty(InputString))
                {
                    ReturnValue = Convert.ToDecimal(InputString, null);
                }
            }
            catch
            {
                ReturnValue = 0;
            }
            return ReturnValue;
        }

        public static decimal? StringToDecimalNull(string InputString)
        {
            decimal? ReturnValue = null;
            try
            {
                if (!String.IsNullOrEmpty(InputString))
                {
                    ReturnValue = Convert.ToDecimal(InputString, null);
                }
            }
            catch
            {
                ReturnValue = null;
            }
            return ReturnValue;
        }

        public static int StringToInt(string InputString)
        {
            int ReturnValue = 0;
            try
            {
                if (!String.IsNullOrEmpty(InputString))
                {
                    ReturnValue = Convert.ToInt32(InputString, null);
                }
            }
            catch
            {
                ReturnValue = 0;
            }
            return ReturnValue;
        }

        public static int? StringToIntNull(string InputString)
        {
            int? ReturnValue = null;
            try
            {
                if (!String.IsNullOrEmpty(InputString))
                {
                    ReturnValue = Convert.ToInt32(InputString, null);
                }
            }
            catch
            {
                ReturnValue = null;
            }
            return ReturnValue;
        }

        /// <summary>
        /// 判断所在是否日期选择的列
        /// </summary>
        /// <param name="fieldName"></param>
        /// <returns></returns>
        public static bool isDateField(DataGridViewColumn theColumn)
        {
            string fieldName = theColumn.DataPropertyName;
            if ((fieldName.ToLower().IndexOf("date") >= 0) || (fieldName.ToLower().IndexOf("expire") >= 0))
                return true;
            else
                return false;
        }

        /// <summary>
        /// 去掉时间部分，只返回日期
        /// </summary>
        /// <param name="StrDateTime"></param>
        /// <returns></returns>
        public static DateTime ToDate(string StrDateTime)
        {
            return Convert.ToDateTime(StrDateTime);
        }

        /// <summary>
        /// 去掉时间部分，只返回日期
        /// </summary>
        /// <param name="TheDateTime"></param>
        /// <returns></returns>
        public static DateTime ToDate(DateTime TheDateTime)
        {
            return Convert.ToDateTime(TheDateTime.ToShortDateString());
        }

        /// <summary>
        /// 递归查找匹配关键字的树节点
        /// </summary>
        /// <param name="node">源节点</param>
        /// <param name="key">关键字</param>
        /// <returns>返回匹配的节点</returns>
        public static TreeNode FindNode(TreeNode node, string key)
        {
            if (node == null) return null;
            if (node.Text.Contains(key)) return node;
            TreeNode tnRet = null;
            foreach (TreeNode tn in node.Nodes)
            {
                tnRet = FindNode(tn, key);
                if (tnRet != null) break;
            }
            return tnRet;
        }

        /// <summary>
        /// 返回分隔后的备注
        /// </summary>
        /// <param name="memo">备注</param>
        /// <returns>备注数组</returns>
        public static string[] ReturnMemo(string memo)
        {
            string spilt = ConfigurationSettings.AppSettings["CommentSplitor"];
            char[] spiltChar = spilt.ToCharArray();
            string[] str = memo.Split(spiltChar);
            return str;
        }

        /// <summary>
        /// 绑定枚举数据到ComboBox
        /// </summary>
        /// <param name="cb"></param>
        /// <param name="enmType"></param>
        public static void BindEnumToComboBox(ComboBox cb, Type enmType)
        {
            cb.Items.Clear();
            foreach (string s in Enum.GetNames(enmType))
                cb.Items.Add(s);
        }

        /// <summary>
        /// MDI窗口是否已经被打开
        /// 已打开的放到最顶层，没打开的创建实例
        /// </summary>
        /// <param name="parentFrm"></param>
        /// <param name="childFrmName"></param>
        /// <returns></returns>
        public static bool MdiFrmIsOpened(Form parentFrm, string childFrmName)
        {
            bool open = false;
            for (int i = 0; i < parentFrm.MdiChildren.Length; i++)
            {
                if (parentFrm.MdiChildren[i].Name == childFrmName)
                {
                    parentFrm.MdiChildren[i].BringToFront();
                    open = true;
                    break;
                }
            }
            return open;
        }

        /// <summary>
        /// DataGridView在行标题列显示行号
        /// 确保RowsHeaderWidthSizeMode属性设置为AutoSizeToAllHeaders或者AutoSizeToDisplayedHeaders以适应文字宽度
        /// 在RowsAdded和RowsRemoved事件里触发
        /// </summary>
        /// <param name="dgv"></param>
        public static void ShowDataGridViewRowNo(DataGridView dgv)
        {
            for (int i = 0; i < dgv.RowCount; i++)
            {
                dgv.Rows[i].HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleRight;
                dgv.Rows[i].HeaderCell.Value = (i + 1).ToString();
            }
        }

        /// <summary>
        /// 动态绑定DGV列架构
        /// </summary>
        /// <param name="dgv">DataGridView</param>
        /// <param name="dgc">DataGridViewColumn类型</param>
        /// <param name="dataPropertyName">绑定数据列名称</param>
        /// <param name="headerText">列标题文本</param>
        /// <param name="visible">是否可见</param>
        /// <param name="readOnly">是否只读</param>
        /// <param name="width">设置宽度</param>
        /// <returns></returns>
        public static int AddDgvColumn(DataGridView dgv, DataGridViewColumn dgc, string dataPropertyName, string headerText, bool? visible, bool? readOnly, int? width)
        {
            try
            {
                dgc.HeaderText = headerText;
                dgc.DataPropertyName = dataPropertyName;
                dgc.Name = "Column_" + (dgv.Columns.Count + 1).ToString();
                if (visible != null)
                    dgc.Visible = Convert.ToBoolean(visible);
                if (readOnly != null)
                    dgc.ReadOnly = Convert.ToBoolean(readOnly);
                if (width != null)
                    dgc.Width = (int)width;
                if (!dgv.Columns.Contains(dgc.Name))
                    return dgv.Columns.Add(dgc);
            }
            catch { }
            return 0;
        }

        #endregion

        #region 右键菜单
        /// <summary>
        /// 添加右键菜单项
        /// </summary>
        /// <param name="text">要显示的菜单文字，如果为空则显示为分割线</param>
        /// <param name="cms">要添加到的子菜单集合</param>
        /// <param name="callback">点击时触发的事件</param>
        /// <param name="enable">菜单是否可用</param>
        /// <param name="chcd">菜单是否勾选中</param>
        /// <returns>生成的子菜单，如果为分隔条则返回null</returns>
        public static ToolStripMenuItem AddContextMenu(string text, ToolStripItemCollection cms, EventHandler callback, bool enable, bool chcd)
        {
            if (text == string.Empty)
            {
                ToolStripSeparator tsp = new ToolStripSeparator();
                cms.Add(tsp);
            }
            else
            {
                ToolStripMenuItem tsmi = new ToolStripMenuItem(text);
                if (callback != null)
                    tsmi.Click += callback;
                tsmi.Enabled = enable;
                tsmi.Checked = chcd;
                cms.Add(tsmi);
                return tsmi;
            }
            return null;
        }
        #endregion
    }
    #endregion

    #region 委托自定义参数
    public class MaterialEventArg : EventArgs
    {
        public MaterialEventArg(TB_Material obj) { this.material = obj; }
        public TB_Material material { get; set; }
        public bool IsNew { get; set; }
    }

    /// <summary>
    /// 通用自定义委托参数
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class CommonEventArg<T> : EventArgs
    {
        /// <summary>
        /// 传递的参数
        /// </summary>
        public T t { get; set; }
        /// <summary>
        /// 委托操作类型
        /// </summary>
        public GRWL.BZSC.UI.Common.OperateType OpType { get; set; }
        public CommonEventArg(T obj, GRWL.BZSC.UI.Common.OperateType opType)
        {
            this.t = obj;
            this.OpType = opType;
        }
    }
    #endregion

    #region Treeview搜索
    /// <summary>
    /// 树节点查找类
    /// </summary>
    public class TreeViewLookUp
    {
        /// <summary>
        /// 查询节点
        /// </summary>
        /// <param name="treeview">treeview控件</param>
        /// <param name="type">查询类型（向上、向下查找）</param>
        /// <param name="QuestName"></param>
        public static void LookUpNode(TreeView treeview, LookUpType type, string key)
        {
            if (treeview.Nodes.Count == 0)
            {
                MessageBox.Show("没有可搜索的内容", "提示");
                return;
            }
            if (type == LookUpType.ADOWN_LOOK)
            {
                if (treeview.SelectedNode != null)
                {
                    treeview.SelectedNode = FindNodeDown(treeview.SelectedNode, key, false);
                }
                else
                {
                    treeview.SelectedNode = FindNodeDown(treeview.Nodes[0], key, true);
                }
                if (treeview.SelectedNode == null)
                {
                    MessageBox.Show(" 已经搜索到最后，系统将会从头开始搜索", "提示");
                }
            }
            if (type == LookUpType.UPTILT_LOOK)
            {
                if (treeview.SelectedNode != null)
                {
                    treeview.SelectedNode = FindNodeUP(treeview.SelectedNode, key, false);
                }
                else
                {
                    treeview.SelectedNode = FindNodeUP(treeview.Nodes[treeview.Nodes.Count - 1], key, true);
                }
                if (treeview.SelectedNode == null)
                {
                    MessageBox.Show(" 已经搜索到最顶，系统将会从头最后搜索", "提示");
                }
            }

        }

        /// <summary>
        /// 向上查找
        /// </summary>
        /// <param name="nodePare">起始节点</param>
        /// <param name="QuestName">要查询的名称</param>
        /// <param name="bl">当前选中节点如果为空</param>
        /// <returns>返回符合的节点，如果为空则没有可是的</returns>
        private static TreeNode FindNodeUP(TreeNode nodePare, string QuestName, bool bl)
        {
            if (nodePare.Text.Contains(QuestName) && bl)//判断是否符合条件
                return nodePare;
            if (nodePare.Nodes.Count > 0)
            {
                TreeNode nodeSelect = FindNodeUP(nodePare.Nodes[nodePare.Nodes.Count - 1], QuestName, true);
                if (nodeSelect != null)
                    return nodeSelect;
            }
            if (nodePare.PrevNode != null)
            {
                TreeNode nodeSelect = FindNodeUP(nodePare.PrevNode, QuestName, true);
                if (nodeSelect != null)
                    return nodeSelect;
            }
            else if (nodePare.Parent != null && nodePare.Parent.PrevNode != null)
            {
                TreeNode nodeSelect = FindNodeUP(nodePare.Parent.PrevNode, QuestName, true);
                if (nodeSelect != null)
                    return nodeSelect;
            }

            return null;
        }


        /// <summary>
        /// 向下查找
        /// </summary>
        /// <param name="nodePare">起始节点</param>
        /// <param name="QuestName">要查询的名称</param>
        /// <param name="bl">当前选中节点如果为空</param>
        /// <returns>返回符合的节点，如果为空则没有可是的</returns>
        private static TreeNode FindNodeDown(TreeNode nodePare, string QuestName, bool bl)
        {
            if (nodePare.Text.Contains(QuestName) && bl)//判断是否符合条件
                return nodePare;
            if (nodePare.Nodes.Count > 0)
            {
                TreeNode nodeSelect = FindNodeDown(nodePare.Nodes[0], QuestName, true);
                if (nodeSelect != null)
                    return nodeSelect;
            }
            if (nodePare.NextNode != null)
            {
                TreeNode nodeSelect = FindNodeDown(nodePare.NextNode, QuestName, true);
                if (nodeSelect != null)
                    return nodeSelect;
            }
            else if (nodePare.Parent != null && nodePare.Parent.NextNode != null)
            {
                TreeNode nodeSelect = FindNodeDown(nodePare.Parent.NextNode, QuestName, true);
                if (nodeSelect != null)
                    return nodeSelect;
            }
            return null;
        }
    }

    /// <summary>
    /// 树节点查找类型
    /// </summary>
    public enum LookUpType
    {
        /// <summary>
        /// 向上查找
        /// </summary>
        UPTILT_LOOK,
        /// <summary>
        /// 向下查找
        /// </summary>
        ADOWN_LOOK,
    }
    #endregion


    #region DataSet/对象相互转换
    /// <summary>   
    /// Represents some utility functions for object-datatable manipulation   
    /// </summary>   
    public sealed class OTConverter
    {
        /// <summary>
        /// 实体属性赋值到DataRow对应字段
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="t">实体</param>
        /// <param name="row">传入DataRow</param>
        public static void ObjectPropertyToDataRow<T>(T obj, DataColumnCollection dcs, DataRow dr)
        {
            try
            {
                Type t = obj.GetType(); //This is used to do the reflection   
                PropertyInfo[] props = obj.GetType().GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
                //dr.BeginEdit();
                foreach (PropertyInfo pro in props)
                {
                    if (dcs.Contains(pro.Name))
                    {
                        object value = pro.GetValue(obj, null);
                        dr[pro.Name] = value == null ? DBNull.Value : value;
                    }
                }
                //dr.EndEdit();
            }
            catch { }
        }

        public static DataRow CovertToDataRow<T>(T t, DataTable tb)
        {
            try
            {
                if (t != null && t is T)
                    return GetDataRow<T>(t, tb);
            }
            catch { }
            return null;
        }

        /// <summary>
        /// DataGridView转换成指定实体类结构的DataTable
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dgv"></param>
        /// <returns></returns>
        public static DataTable ConvertToDataTable<T>(DataGridView dgv) where T : new()
        {
            T obj = new T();
            DataTable dt = new DataTable(typeof(T).Name);
            System.Reflection.PropertyInfo[] myPropertyInfo = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
            for (int i = 0, j = myPropertyInfo.Length; i < j; i++)
            {
                System.Reflection.PropertyInfo pi = myPropertyInfo[i];

                if (dt.Columns[pi.Name] == null)
                {
                    DataColumn dc = new DataColumn();
                    dc.AllowDBNull = true;
                    dc.ColumnName = pi.Name;
                    Type colType = pi.PropertyType;
                    if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition() == typeof(Nullable<>)))
                        colType = colType.GetGenericArguments()[0];
                    dc.DataType = colType;
                    dt.Columns.Add(dc);
                    //dt.Columns.Add(new DataColumn(name, pi.PropertyType));
                }
            }

            if (dgv.Rows.Count > 0)
            {
                for (int i = 0; i < dgv.Rows.Count; i++)
                {
                    DataRow row = dt.NewRow();
                    for (int j = 0; j < dgv.Rows[i].Cells.Count; j++)
                    {
                        if (ExistsColumnName(dt.Columns, dgv.Columns[j].Name))
                            row[dgv.Columns[j].Name] = dgv.Rows[i].Cells[j].Value;
                    }
                    dt.Rows.Add(row);
                }
            }
            return dt;
        }

        /// <summary>
        /// 实体架构映射到DataGirdView
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dgv"></param>
        public static void MapToDataGirdView<T>(DataGridView dgv, string[] notDisplays, object obj)
        {
            PropertyInfo[] proInfos = typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public);
            int colID;
            for (int i = 0; i < proInfos.Length; i++)
            {
                PropertyInfo pi = proInfos[i];
                //if (pi.IsDefined(typeof(ColumnVisibleAttribute), false)) 
                //{
                if (pi.PropertyType == obj.GetType())
                {
                    PropertyInfo[] childProps = obj.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
                    foreach (PropertyInfo p in childProps)
                    {
                        //ColumnVisibleAttribute colVis = p.GetCustomAttributes(typeof(ColumnVisibleAttribute), false)[0] as ColumnVisibleAttribute;
                        colID = dgv.Columns.Add(p.Name, p.Name);
                        dgv.Columns[colID].DataPropertyName = p.Name;
                        if (notDisplays.Contains(p.Name))
                            dgv.Columns[colID].Visible = false;
                    }
                }
                else
                {
                    //ColumnVisibleAttribute colVis = pi.GetCustomAttributes(typeof(ColumnVisibleAttribute), false)[0] as ColumnVisibleAttribute;
                    //colID = dgv.Columns.Add(pi.Name, colVis.CustomName);
                    //dgv.Columns[colID].DataPropertyName = pi.Name;
                    //if (notDisplays.Contains(pi.Name))
                    //    dgv.Columns[colID].Visible = false;
                }
                //} 
            }
        }

        /// <summary>
        /// DataGridView转换成指定实体类结构的序列
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dgv"></param>
        /// <returns></returns>
        public static List<T> ConvertDgvToObjectList<T>(DataGridView dgv, string[] notDisplays, object xObj) where T : new()
        {
            List<T> list = null;
            T obj = new T();
            System.Reflection.PropertyInfo[] myPropertyInfo = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
            if (dgv.Rows.Count > 0)
            {
                list = new List<T>();
                for (int i = 0; i < dgv.Rows.Count; i++)
                {
                    T newObj = new T();
                    for (int p = 0, j = myPropertyInfo.Length; p < j; p++)
                    {
                        if (xObj != null && myPropertyInfo[p].PropertyType == xObj.GetType())
                        {
                            PropertyInfo[] childProps = (myPropertyInfo[p].GetValue(xObj, null)).GetType().GetProperties();
                            //PropertyInfo[] childProps = xObj.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
                            foreach (PropertyInfo c in childProps)//子类
                            {
                                if (dgv.Columns[c.Name] != null && !notDisplays.Contains(c.Name))
                                {
                                    Type colType = c.PropertyType;
                                    if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition() == typeof(Nullable<>)))
                                        colType = colType.GetGenericArguments()[0];
                                    object value = dgv.Rows[i].Cells[c.Name].Value;
                                    if (value != null)
                                    {
                                        object nValue = Convert.ChangeType(value, colType);
                                        c.SetValue(xObj, nValue, null);
                                    }
                                }
                            }
                        }

                        if (dgv.Columns[myPropertyInfo[p].Name] != null && !notDisplays.Contains(myPropertyInfo[p].Name))
                        {
                            Type colType = myPropertyInfo[p].PropertyType;
                            if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition() == typeof(Nullable<>)))
                                colType = colType.GetGenericArguments()[0];
                            object value = dgv.Rows[i].Cells[myPropertyInfo[p].Name].Value;
                            if (value != null)
                            {
                                object nValue = Convert.ChangeType(value, colType);
                                myPropertyInfo[p].SetValue(newObj, nValue, null);
                            }
                        }
                    }
                    list.Add(newObj);
                }
            }
            return list;
        }

        /// <summary>   
        /// Convert an DataRow to an object   
        /// </summary>   
        /// <typeparam name="T"></typeparam>   
        /// <param name="row"></param>   
        /// <returns></returns>   
        public static T ConvertToObject<T>(DataRow row) where T : new()
        {
            object obj = new T();
            if (row != null)
            {
                DataTable t = row.Table;
                GetObject(t.Columns, row, obj);
            }
            if (obj != null && obj is T)
                return (T)obj;
            else
                return default(T);

        }

        /// <summary>   
        /// Convert a data table to an objct list   
        /// </summary>   
        /// <typeparam name="T"></typeparam>   
        /// <param name="t"></param>   
        /// <returns></returns>   
        public static List<T> ConvertTableToObject<T>(DataTable t) where T : new()
        {
            List<T> list = new List<T>();
            foreach (DataRow row in t.Rows)
            {
                T obj = ConvertToObject<T>(row);
                list.Add(obj);
            }

            return list;



        }

        /// <summary>   
        /// Convert object collection to an data table   
        /// </summary>   
        /// <param name="list"></param>   
        /// <returns></returns>   
        public static DataTable GenericListToDataTable(object list)
        {
            DataTable dt = null;
            Type listType = list.GetType();
            if (listType.IsGenericType)
            {
                //determine the underlying type the List<> contains   
                Type elementType = listType.GetGenericArguments()[0];

                //create empty table -- give it a name in case   
                //it needs to be serialized   
                dt = new DataTable(elementType.Name + "List");

                //define the table -- add a column for each public   
                //property or field   
                MemberInfo[] miArray = elementType.GetMembers(
                    BindingFlags.Public | BindingFlags.Instance);
                foreach (MemberInfo mi in miArray)
                {
                    if (mi.MemberType == MemberTypes.Property)
                    {
                        PropertyInfo pi = mi as PropertyInfo;
                        dt.Columns.Add(pi.Name, pi.PropertyType);
                    }
                    else if (mi.MemberType == MemberTypes.Field)
                    {
                        FieldInfo fi = mi as FieldInfo;
                        dt.Columns.Add(fi.Name, fi.FieldType);
                    }
                }

                //populate the table   
                IList il = list as IList;
                foreach (object record in il)
                {
                    int i = 0;
                    object[] fieldValues = new object[dt.Columns.Count];
                    foreach (DataColumn c in dt.Columns)
                    {
                        MemberInfo mi = elementType.GetMember(c.ColumnName)[0];
                        if (mi.MemberType == MemberTypes.Property)
                        {
                            PropertyInfo pi = mi as PropertyInfo;
                            fieldValues[i] = pi.GetValue(record, null);
                        }
                        else if (mi.MemberType == MemberTypes.Field)
                        {
                            FieldInfo fi = mi as FieldInfo;
                            fieldValues[i] = fi.GetValue(record);
                        }
                        i++;
                    }
                    dt.Rows.Add(fieldValues);
                }
            }
            return dt;
        }
        #region
        /// <summary>
        /// 将输入DataGridView中的数据转换成DataTable
        /// </summary>
        /// <param name="dgv">DataGridView控件</param>
        /// <returns>返回DataTable</returns>
        public static DataTable GetDgvToTable(DataGridView dgv)
        {
            DataTable dt = new DataTable();
            for (int count = 0; count < dgv.Rows.Count; count++)
            {
                DataRow dr = (dgv.Rows[count].DataBoundItem as DataRowView).Row;
                dt.Rows.Add(dr);
            }
            return dt;
        }
        #endregion


        #region "internal methods"
        private static void GetObject(DataColumnCollection cols, DataRow dr, Object obj)
        {
            Type t = obj.GetType(); //This is used to do the reflection   
            PropertyInfo[] props = obj.GetType().GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
            //PropertyInfo[] props = t.GetProperties();
            foreach (PropertyInfo pro in props)
            {
                if (ExistsColumnName(cols, pro.Name))
                {
                    Type colType = pro.PropertyType;

                    pro.SetValue(obj,
                        dr[pro.Name] == DBNull.Value ? null : dr[pro.Name],
                        null);
                }
            }


            //for (Int32 i = 0; i <= cols.Count - 1; i++)   
            //{   
            //    try   
            //    {  //NOTE the datarow column names must match exactly (including case) to the object property names   
            //        t.InvokeMember(cols[i].ColumnName   
            //            , BindingFlags.SetProperty   
            //            , null   
            //            , obj   
            //            , new object[] { dr[cols[i].ColumnName] });   
            //    }   
            //    catch (Exception ex)   
            //    { //Usually you are getting here because a column doesn't exist or it is null   
            //        if (ex.ToString() != null)   
            //        {   
            //        }   
            //    }   
            //};   
        }

        private static DataRow GetDataRow<T>(T obj, DataTable tb)
        {
            try
            {
                DataRow dr = tb.NewRow();
                Type t = obj.GetType(); //This is used to do the reflection   
                PropertyInfo[] props = obj.GetType().GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
                //PropertyInfo[] props = t.GetProperties();
                foreach (PropertyInfo pro in props)
                {
                    if (ExistsColumnName(tb.Columns, pro.Name))
                        dr[pro.Name] = pro.GetValue(obj, null);
                }
            }
            catch { }
            return null;
        }

        private static bool ExistsColumnName(DataColumnCollection cols, string name)
        {
            foreach (DataColumn c in cols)
            {
                if (c.ColumnName.ToLower() == name.ToLower())
                    return true;
            }
            return false;
        }

        #endregion
    }
    #endregion

    #region IEnumerable扩充
    /// <summary>     
    /// IEnumerable 擴充方法     
    /// </summary>     
    public static class IEnumerableExtensions
    {
        /// <summary>     
        /// 將 IEnumerable 轉換至 DataTable     
        /// </summary>     
        /// <param name="list">IEnumerable</param>     
        /// <returns>DataTable</returns>     
        public static DataTable ToDataTable(this IEnumerable list)
        {
            DataTable dt = new DataTable();
            //bool schemaIsBuild = false;
            PropertyInfo[] props = null;
            bool isCreatedColumn = false;
            foreach (object item in list)
            {
                //if (!schemaIsBuild)
                //{
                ArrayList ary = new ArrayList();
                props = item.GetType().GetProperties();
                foreach (var pi in props)
                {
                    //if (ExistsColumnName(dt.Columns, pi.Name))
                    //    row[pi.Name] = pi.GetValue(item, null);
                    //dt.Columns.Add(new DataColumn(pi.Name, pi.PropertyType));

                    //dt.Rows.Add(row);
                    //schemaIsBuild = true;

                    if (pi.Name.ToLower() != "extensiondata")
                    {
                        if (!isCreatedColumn)
                        {
                            DataColumn dc = new DataColumn();
                            dc.AllowDBNull = true;
                            dc.ColumnName = pi.Name;
                            Type colType = pi.PropertyType;
                            if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition() == typeof(Nullable<>)))
                                colType = colType.GetGenericArguments()[0];
                            dc.DataType = colType;
                            dt.Columns.Add(dc);
                        }


                        ary.Add(pi.GetValue(item, null));
                    }
                }
                object[] row = new object[ary.Count];
                ary.CopyTo(row);
                dt.Rows.Add(row);
                if (!isCreatedColumn)
                    isCreatedColumn = true;
                //}





                //var row = dt.NewRow();
                //foreach (var pi in props)
                //{
                //    row[pi.Name] = pi.GetValue(item, null);
                //}

                //dt.Rows.Add(row);
            }

            dt.AcceptChanges();
            return dt;
        }

        /// <summary>
        /// 把包含子类对象的复合类对象序列转换为DataTable,以便加载数据到控件
        /// </summary>
        /// <typeparam name="T">包含的子类对象</typeparam>
        /// <param name="list">复合类对象序列</param>
        /// <param name="dt">控件定义好架构的DataTable</param>
        /// <returns>DataTable</returns>
        public static DataTable ConvertToDataTable<T>(this IEnumerable list, DataTable dt)
        {
            //DataTable dt = new DataTable();
            bool schemaIsBuild = false;
            PropertyInfo[] props = null;

            foreach (object item in list)
            {
                if (!schemaIsBuild)
                {
                    DataRow row = dt.NewRow();
                    props = item.GetType().GetProperties();
                    foreach (PropertyInfo pi in props)
                    {
                        if (pi.PropertyType == typeof(T))
                        {
                            PropertyInfo[] childProps = ((T)pi.GetValue(item, null)).GetType().GetProperties();
                            foreach (PropertyInfo p in childProps)
                            {
                                if (ExistsColumnName(dt.Columns, pi.Name))
                                    row[p.Name] = p.GetValue(pi, null);
                            }
                        }
                        else
                        {
                            if (ExistsColumnName(dt.Columns, pi.Name))
                                row[pi.Name] = pi.GetValue(item, null);
                        }
                    }

                    dt.Rows.Add(row);
                    schemaIsBuild = true;
                }
            }
            dt.AcceptChanges();
            return dt;
        }

        /// <summary>
        /// 把包含子类对象的复合类对象序列转换为DataTable,以便加载数据到控件
        /// </summary>
        /// <typeparam name="T">包含的子类对象</typeparam>
        /// <param name="list">复合类对象序列</param>
        /// <returns>DataTable</returns>
        public static DataTable ConvertToDataTable<T>(this IEnumerable list)
        {
            DataTable dt = new DataTable();
            //bool schemaIsBuild = false;
            PropertyInfo[] props = null;
            bool isCreatedColumn = false;

            //Array.ForEach<PropertyInfo>(list.get.GetProperties(), p => { pList.Add(p); dt.Columns.Add(p.Name, p.PropertyType); });

            foreach (object item in list)
            {
                //if (!schemaIsBuild)
                //{
                ArrayList ary = new ArrayList();
                //DataRow row = dt.NewRow();
                props = item.GetType().GetProperties();
                foreach (PropertyInfo pi in props)
                {
                    if (pi.PropertyType == typeof(T))
                    {
                        PropertyInfo[] childProps = ((T)pi.GetValue(item, null)).GetType().GetProperties();
                        foreach (PropertyInfo p in childProps)
                        {
                            if (p.Name.ToLower() != "extensiondata")
                            {
                                if (!isCreatedColumn)
                                {
                                    DataColumn dc = new DataColumn();
                                    dc.AllowDBNull = true;
                                    dc.ColumnName = p.Name;
                                    Type colType = p.PropertyType;
                                    if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition() == typeof(Nullable<>)))
                                        colType = colType.GetGenericArguments()[0];
                                    dc.DataType = colType;
                                    dt.Columns.Add(dc);
                                }
                                ary.Add(p.GetValue((T)pi.GetValue(item, null), null));
                                //dt.Columns.Add(new DataColumn(p.Name, p.PropertyType));
                                //row[p.Name] = p.GetValue(pi, null);
                            }
                        }
                    }
                    else
                    {
                        if (pi.Name.ToLower() != "extensiondata")
                        {
                            if (!isCreatedColumn)
                            {
                                DataColumn dc = new DataColumn();
                                dc.AllowDBNull = true;
                                dc.ColumnName = pi.Name;
                                Type colType = pi.PropertyType;
                                if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition() == typeof(Nullable<>)))
                                    colType = colType.GetGenericArguments()[0];
                                dc.DataType = colType;
                                dt.Columns.Add(dc);
                            }


                            ary.Add(pi.GetValue(item, null));
                        }
                    }
                }
                object[] row = new object[ary.Count];
                ary.CopyTo(row);
                dt.Rows.Add(row);
                if (!isCreatedColumn)
                    isCreatedColumn = true;
                //schemaIsBuild = true;
                //}
            }
            dt.AcceptChanges();
            return dt;
        }

        private static bool ExistsColumnName(DataColumnCollection cols, string name)
        {
            foreach (DataColumn c in cols)
            {
                if (c.ColumnName.ToLower() == name.ToLower())
                    return true;
            }
            return false;
        }
    }
    #endregion

    #region 自定义属性
    [global::System.AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
    public sealed class ColumnVisibleAttribute : Attribute
    {
        public ColumnVisibleAttribute(string custom) : this(custom, true) { }
        public ColumnVisibleAttribute(string customName, bool isDisplay) { this._customName = customName; this._display = IsDisplay; }
        private bool _display;
        public bool IsDisplay { get { return _display; } set { _display = value; } }
        private string _customName;
        public string CustomName { get { return _customName; } set { _customName = value; } }
    }
    #endregion
}
